home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume4 / uk-1.4 / part5 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  40.9 KB

  1. From: Jim Crammond <seismo!mcvax!cs.hw.ac.uk!jim>
  2. Subject: Sendmail UK-1.4 part 5 of 5
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 60
  7. Submitted by: Jim Crammond <seismo!mcvax!cs.hw.ac.uk!jim>
  8.  
  9.  
  10. #    This is a shell archive.
  11. #    Remove everything above and including the cut line.
  12. #    Then run the rest of the file through sh.
  13. -----cut here-----cut here-----cut here-----cut here-----
  14. #!/bin/sh
  15. # shar:    Shell Archiver
  16. #    Run the following text with /bin/sh to create:
  17. #    xtras
  18. # This archive created: Mon Mar 17 16:57:06 1986
  19. echo shar: creating directory xtras
  20. mkdir xtras
  21. cd xtras
  22. echo shar: extracting SysV.sh '(866 characters)'
  23. cat << \SHAR_EOF > SysV.sh
  24. #!/bin/sh
  25. #
  26. #  This shell script converts the BSD dependent parts of the MAKE shell
  27. #  scripts into something suitable for SystemV.
  28. #
  29. #  This must be run in the top level directory of the sendmail package.
  30. #
  31.  
  32. for i in MAKE chn/MAKE dom/MAKE
  33. do
  34.     if [ ! -f $i ]
  35.     then
  36.         echo $i non-existent
  37.         exit 1
  38.     fi
  39.  
  40.     if [ ! -f $i.bsd ]
  41.     then
  42.         mv $i $i.bsd
  43.     fi
  44. done
  45.  
  46.  
  47. #  The top level make file
  48.  
  49. sed    -e 's/echo -n/echo/'        \
  50.     -e 's/? "/? \\c"/'        \
  51.     -e 's/: "/: \\c"/'        \
  52.     -e 's/(y|n) "/(y|n) \\c"/'    \
  53.     -e '/Complete/s/\."/.\\c"/'    \
  54.     -e '/^Making/s/\.\. /.. \\c/'    \
  55.     -e '/^creating/s/\.\. /.. \\c/'    MAKE.bsd > MAKE
  56.  
  57. #  The channel make file
  58.  
  59. sed    -e "s;fmt | sed;nroff | sed -e '/^$/d' -e;"    chn/MAKE.bsd > chn/MAKE
  60.  
  61. #  The domain make file
  62.  
  63. sed    -e "s;tail -r \(S..\);pr -t -n \1 | sort -r | sed 's/^......//';" \
  64.     -e "s;fmt | sed;nroff | sed -e '/^$/d' -e;"    dom/MAKE.bsd > dom/MAKE
  65. SHAR_EOF
  66. if test 866 -ne "`wc -c SysV.sh`"
  67. then
  68. echo shar: error transmitting SysV.sh '(should have been 866 characters)'
  69. else
  70. chmod a+x SysV.sh
  71. fi
  72. echo shar: extracting distribute '(781 characters)'
  73. cat << \SHAR_EOF > distribute
  74. #!/bin/sh
  75. #
  76. #  Send a mail message to users on a distribution list.  The message header is
  77. #  altered mainly to allow error messages to be returned to the list maintainer.
  78. #  This script should be setuid to one of sendmail's trusted users.
  79. #
  80. #  Usage: put an entry into /usr/lib/aliases of the following form:
  81. #
  82. #    list-name: "|/usr/local/lib/distribute list-name user1 user2 ..."
  83. #
  84.  
  85. if [ $# -lt 2 ]
  86. then
  87.     echo Usage: $0 list-name user1 user2 ...
  88.     exit 64
  89. fi
  90.  
  91. dlist=$1
  92. shift
  93.  
  94. sed -e '1,/^$/s/^$/EOH\
  95. /'                    |
  96. sed -e '/^$/,$b'            \
  97.     -e '/^From /d'            \
  98.     -e '/^Via:/s//Original-Via:/'    \
  99.     -e '/^Sender:/s//Original-Sender:/'    \
  100.     -e '/^Acknowledge-To:/d'        \
  101.     -e '/^Return-Receipt-To:/d'        \
  102.     -e "/^EOH$/s//Sender: $dlist-request/" |
  103.  
  104. /usr/lib/sendmail -f$dlist-request $*
  105. SHAR_EOF
  106. if test 781 -ne "`wc -c distribute`"
  107. then
  108. echo shar: error transmitting distribute '(should have been 781 characters)'
  109. else
  110. chmod a+x distribute
  111. fi
  112. echo shar: extracting sendproc.sh '(1762 characters)'
  113. cat << \SHAR_EOF > sendproc.sh
  114. #! /bin/sh
  115. file=${1-NRS}
  116. date=`date`
  117. # if a berkeley 4.2 site use this
  118.  
  119. sed -n -e '/^\.H1 Reverse/q' \
  120.     -e '/^\.H1 Context MAIL-NIFTP Subnetwork JANET/,/^\.H1/p' \
  121.     -e '/^\.H1 Context MAIL-NIFTP Subnetwork PSS/,/^\.H1/p' $file |
  122. tr '[A-Z]' '[a-z]' |
  123. awk '
  124. BEGIN    {
  125.     tmp1 = "/tmp/sm.1"
  126.     tmp2 = "/tmp/sm.2"
  127.     tmp3 = "/tmp/sm.3"
  128.     tmp4 = "/tmp/sm.4"
  129.     }
  130.  
  131. /^standard name/    {    long = $3    }
  132. /^abbreviated name/    {    short = $3    }
  133. /^$/    {
  134.     ln = split(long, ldom, ".");
  135.     sn = split(short, sdom, ".");
  136.  
  137.     if (long ~ /uk\./)
  138.     {    if (ln == 2)
  139.             printf "%-20s %s.%s\n", ldom[2],ldom[2],ldom[1] > tmp1
  140.         else
  141.             printf "%-20s %s.%s.%s\n", ldom[3],ldom[3],ldom[2],ldom[1] > tmp1
  142.     }
  143.     
  144.     if (short ~ /uk\./)
  145.     {    if (ln == 2 && sdom[2] != ldom[2])
  146.             printf "%-12s %s.%s\n", sdom[2],sdom[2],sdom[1] > tmp2
  147.         else if (ln >= 3 && sdom[3] != ldom[3])
  148.             printf "%-12s %s.%s.%s\n", sdom[3],sdom[3],sdom[2],sdom[1] > tmp2
  149.     }
  150.  
  151.     if (long != short)
  152.     {    l1 = "" ;  s1 = ""
  153.         if (ln > 2)    l1 = ldom[3] "."
  154.         if (sn > 2)    s1 = sdom[3] "."
  155.         l1 = l1 ldom[2] "." ldom[1]
  156.         s1 = s1 sdom[2] "." sdom[1]
  157.  
  158.         l2 = "" ;  s2 = ""
  159.         if (ln > 3)
  160.         {    l2 = ldom[ln]
  161.             for (j=ln-1; j>=4; j--)    l2 = l2 "." ldom[j]
  162.         }
  163.         if (sn > 3)
  164.         {    s2 = sdom[sn]
  165.             for (j=sn-1; j>=4; j--)    s2 = s2 "." sdom[j]
  166.         }
  167.  
  168.         if (l2 != s2)
  169.         {    l1 = l2 "." l1
  170.             s1 = s2 "." s1
  171.             printf "%-18s %s\n", s1, l1    > tmp3
  172.         }
  173.         else
  174.             printf "%-18s %s\n", s1, l1    > tmp4
  175.     }
  176.         short = long = ""
  177.     }
  178. '
  179.  
  180. cat > uk.dom <<EOF
  181. #
  182. #  UK Domain Table.  Generated: $date
  183. #
  184. # Standard form names
  185. #
  186. `sort /tmp/sm.1 | uniq`
  187. #
  188. # Abbreviated form names
  189. #
  190. `sort /tmp/sm.2 | uniq`
  191. EOF
  192.  
  193. cat > abbrev.dom <<EOF
  194. #
  195. #  Abbreviated form to Standard form table.
  196. #    Generated: $date
  197. #
  198. `sort /tmp/sm.3 | uniq`
  199. `sort /tmp/sm.4 | uniq`
  200. EOF
  201.  
  202. /bin/rm /tmp/sm.[1234]
  203. exit
  204. SHAR_EOF
  205. if test 1762 -ne "`wc -c sendproc.sh`"
  206. then
  207. echo shar: error transmitting sendproc.sh '(should have been 1762 characters)'
  208. else
  209. chmod a+x sendproc.sh
  210. fi
  211. echo shar: extracting checkaddr '(1594 characters)'
  212. cat << \SHAR_EOF > checkaddr
  213. #!/bin/sh
  214. # shell script to verify what sendmail would do with given addresses
  215. # this version works for sendmail version 4.12
  216.  
  217. verbose=false
  218. if [ $1 = "-v" ]
  219. then
  220.     verbose=true
  221.     shift
  222. fi
  223.  
  224. trap "/bin/rm /tmp/ver.$$; exit" 1 2 3 15
  225.  
  226. while [ $# -ge 1 ]
  227. do
  228.     echo -n "$1: "
  229.  
  230.     /usr/lib/sendmail -bt > /tmp/ver.$$  <<EOF
  231. 0 $1
  232. EOF
  233.  
  234.     if grep -s 'ruleset  0 returns: "^U" "local"' /tmp/ver.$$
  235.     then
  236.         if /usr/lib/sendmail -bv $1 > /tmp/ver.$$
  237.         then
  238.         echo addr OK
  239.         else
  240.         sed -n -e '/deliverable/d'    \
  241.                -e 's/\(.*\)\.\.\. \(.*\)/\2  (\1)/p' /tmp/ver.$$
  242.         fi
  243.         if $verbose
  244.         then
  245.         aliases=""
  246.         for a in `sed -n 's/\.\.\. deliverable//p' /tmp/ver.$$`
  247.         do
  248.             if [ "$a" = "$1" ]
  249.             then
  250.             echo "Routed to:  channel=local,  addr=$a"
  251.             else
  252.             aliases="$aliases $a"
  253.             fi
  254.         done
  255.         if [ -n "$aliases" ]
  256.         then
  257.             echo "Aliased to:$aliases"
  258.             $0 $aliases
  259.         fi
  260.         fi
  261.     elif grep -s 'ruleset  0 returns: "^U" "error"' /tmp/ver.$$
  262.     then
  263.         sed -n -e 's/"\([^"]*\)"/\1/g'    \
  264.         -e '/ruleset  0 returns:/s/.*^W //p' /tmp/ver.$$
  265.     else
  266.         echo addr OK
  267.         if $verbose
  268.         then
  269.         sed -n '/ruleset  3 returns:/s/.*returns: //p' /tmp/ver.$$ |
  270.         sed -n -e '$s/"\([^"]*\)"/\1/g' \
  271.             -e '$s/ \([!.@%]\) /\1/g'    \
  272.             -e '$s/^/Normalised to: /p' 
  273.  
  274.         sed -n '/ruleset  0 returns:/s/.*^U" //p' /tmp/ver.$$ |
  275.         sed -e 's/"\([^"]*\)"/\1/g'    \
  276.             -e 's/\(.*\) ^V \(.*\) ^W \(.*\)/Routed to:  channel=\1,  host=\2,  addr=\3/'\
  277.             -e 's/\(.*\) ^W \(.*\)/Routed to:  channel=\1,  addr=\2/'    \
  278.             -e 's/ \([!.@%]\) /\1/g'
  279.         fi
  280.     fi
  281.  
  282.     /bin/rm /tmp/ver.$$
  283.     shift
  284. done
  285. SHAR_EOF
  286. if test 1594 -ne "`wc -c checkaddr`"
  287. then
  288. echo shar: error transmitting checkaddr '(should have been 1594 characters)'
  289. else
  290. chmod a+x checkaddr
  291. fi
  292. echo shar: extracting csnet.note '(2947 characters)'
  293. cat << \SHAR_EOF > csnet.note
  294. This note contains a few hints on how csnet sites should configure
  295. their tables from information provided from info@sh.cs.net (info@csnet-sh)
  296.  
  297. Domain Tables
  298. ------ ------
  299. The CSNet information service provides you with the necessary "host tables"
  300. to create your domain and channel tables, almost automatically.
  301.  
  302. There are three host tables that you can choose from:
  303.  
  304.     tbl-4a contains the TOP table, the CSNET table and the ARPA table.
  305.     tbl-4c contains the TOP table and the CSNET table only.
  306.     tbl-4t contains the TOP table only.
  307.  
  308. The CIC recommend that you just use the TOP table, tbl-4t, and forward
  309. everything to csnet-relay.  This is certainly the easiest option to take.
  310. It is quite feasible to include the CSNET table too: this will allow you
  311. to mail to "user@csnet-host" and let sendmail expand that to a domain name.
  312. Without this table, you have to mail to "user@csnet-host_._c_s_n_e_t" every time.
  313. However, I would strongly recommend that you do NOT attempt to include the
  314. ARPA table as well, since this table is so large.
  315.  
  316. To obtain the TOP and CSNET tables, mail to info@sh.cs.net (info@csnet-sh)
  317. with the following lines in the message body:
  318.  
  319.     Request: info
  320.     Topic: tbl-4c
  321.     Request: end
  322.  
  323. The TOP table looks like this:
  324.  
  325.     ARPA    Forward to CSNET-RELAY.ARPA
  326.     COM     Forward to CSNET-RELAY.ARPA
  327.     EDU     Forward to CSNET-RELAY.ARPA
  328.     GOV     Forward to CSNET-RELAY.ARPA
  329.     MIL     Forward to CSNET-RELAY.ARPA
  330.     NET     Forward to CSNET-RELAY.ARPA
  331.     ORG     Forward to CSNET-RELAY.ARPA
  332.     UK      Forward to CSNET-RELAY.ARPA
  333.     US      Forward to CSNET-RELAY.ARPA
  334.  
  335. This can be converted into the sendmail _t_o_p_._d_o_m by the command:
  336.     
  337.     "sed 's/Forward to//' | tr '[A-Z]' '[a-z]'"
  338.  
  339. (Strictly speaking the tr command - to lowercase the names - is unnecessary.
  340.  Sendmail is not fussy, - I just like to see lowercase tables!)
  341.  
  342. The CSNET table looks like this:
  343.  
  344.     CSNET-RELAY CSNET-RELAY.CSNET
  345.     CSNET-SH CSNET-SH.CSNET
  346.     CSNET-CIC CSNET-SH.CSNET
  347.     ALBANY ALBANY.CSNET
  348.     SUNYA ALBANY.CSNET
  349.     SUNY-A ALBANY.CSNET
  350.     etc.
  351.  
  352. This can be converted into the sendmail _c_s_n_e_t_._d_o_m by the command:
  353.  
  354.     "sed 's/,.*//' | tr '[A-Z]' '[a-z]'"
  355.  
  356. (The sed command removes relay information, the tr command lowercases names.)
  357.  
  358. Channel Tables
  359. ------- ------
  360. The _t_o_p_._c_h_n channel table is linked/copied from top.dom in the domain tables.
  361. The top.dom defines the top level domains to recognise, the top.chn specifies
  362. the relay domain to route them to - i.e. csnet-relay.arpa.
  363.  
  364. The _c_s_n_e_t_._c_h_n table contains the domain name(s) of the relay site on the LHS
  365. and the host name of the relay on the RHS. Thus, for csnet-relay you should
  366. have:
  367.     csnet-relay.arpa    csnet-relay
  368.     csnet-relay.csnet    csnet-relay
  369.     relay.cs.net        csnet-relay
  370.  
  371. Finally, the _l_o_c_a_l_._c_h_n table should contain your hosts domain name(s).
  372.  
  373.  
  374. Examples of these tables can be found in the Examples.a files in the
  375. dom and chn directories.
  376. SHAR_EOF
  377. if test 2947 -ne "`wc -c csnet.note`"
  378. then
  379. echo shar: error transmitting csnet.note '(should have been 2947 characters)'
  380. fi
  381. echo shar: extracting checkaddr.1 '(622 characters)'
  382. cat << \SHAR_EOF > checkaddr.1
  383. .TH CHECKADDR 1 "UK-sendmail"
  384. .UC 4
  385. .SH NAME
  386. checkaddr - sendmail address verification program
  387. .SH SYNOPSIS
  388. .B checkaddr
  389. [-v]
  390. .B addresses...
  391. .SH DESCRIPTION
  392. The
  393. .I checkaddr
  394. program is used to check the validity of any address  with
  395. the local mail system (sendmail).  
  396. A list of  addresses  is given on the command line,
  397. checkaddr will then announce each
  398. address on a separate line and follow the address with its status
  399. (normally  ``addr OK'').  
  400. .PP
  401. By specifying the -v flag, checkaddr will print additional information
  402. about how it
  403. .I normalises
  404. the address and 
  405. what routing it then does.
  406. .SH "SEE ALSO"
  407. sendmail(8)
  408. SHAR_EOF
  409. if test 622 -ne "`wc -c checkaddr.1`"
  410. then
  411. echo shar: error transmitting checkaddr.1 '(should have been 622 characters)'
  412. fi
  413. echo shar: extracting uknet.note '(4566 characters)'
  414. cat << \SHAR_EOF > uknet.note
  415. This note contains a few hints on what information you should have
  416. in your sendmail tables to cope with the new naming scheme.
  417.  
  418. Domain Tables
  419. ------ ------
  420. There are two domain tables that you need to include in your configuration:
  421.  
  422. 1. uk.dom
  423.     This table lists all the subdomains of ac.uk and co.uk.
  424.  
  425.     It allows users to specify partially qualified names
  426.     and let sendmail expand them to fully qualified names,
  427.     e.g  jim@cs.heriot-watt  =>  jim@cs.heriot-watt.ac.uk
  428.  
  429.     The UK-1.4 distribution contains such a table and updates
  430.     will hopefully be posted to uk.net on a regular basis.
  431.     This can be included as is. Perhaps the only change that you
  432.     may want to make to the distributed table is to remove the
  433.     entry for "co.ac.uk" which causes a name clash with "co.uk".
  434.  
  435. 2. ukuucp.dom
  436.     This table contains a list of entries of the form
  437.  
  438.         uucpname    domainname
  439.  
  440.     Only those uucp sites directly connected to your site need
  441.     to be included in this table.  For example, here is the table
  442.     we have at hwcs:
  443.  
  444.         aimmi        aimmi.ac.uk
  445.         cstvax       cstvax.ed.ac.uk
  446.         dice         dice.ferr.co.uk
  447.         edcaad       caad.ed.ac.uk
  448.         hwcs         cs.hw.ac.uk
  449.         kcl-cs       cs.kcl.ac.uk
  450.         spider       spider.co.uk
  451.         stl          stl.stc.co.uk
  452.         ulcs         dcs.leeds.ac.uk
  453.  
  454.     This is particularly important for those directly connected sites
  455.     which have V7mailers, as they will be relying on you to convert
  456.     their uucpname to their domain name.
  457.  
  458. There is a third domain table that you can include, which converts the
  459. abbreviated form of addresses to standard form.  This, however, generates
  460. a lot of rules and so is only really practical on machines in which
  461. the "freeze file" works.  This will be made available on uk.net shortly. 
  462.  
  463.  
  464. Channel Tables
  465. ------- ------
  466. There are four scenarios to consider here.
  467.  
  468. 1.  An academic site on Janet.
  469.     Most of the routing in this case will be done by the x25 software
  470.     as all UKnet sites not directly connected to Janet will have a
  471.     Janet site registered as a relay to it.  Thus hhcp forwards the
  472.     mail to the relay.
  473.  
  474.     If there are UKnet sites using you as a Janet relay, then obviously
  475.     the important thing is to have them in your uucp.chn table!
  476.  
  477.     As an example, cstvax.ed.ac.uk is likely to be the relay for a
  478.     number of Edinburgh uucp sites.  Their uucp.chn table will probably
  479.     look something like this:
  480.  
  481.         caad.edinburgh.ac.uk    edcaad!%s
  482.         caad.ed.ac.uk        edcaad!%s
  483.         cs.heriot-watt.ac.uk    hwcs!%s
  484.         cs.hw.ac.uk        hwcs!%s
  485.         dice.ferranti.co.uk    hwcs!dice!%s
  486.         dice.ferr.co.uk        hwcs!dice!%s
  487.         spider.co.uk        hwcs!spider!%s
  488.  
  489.     Note that both standard and abbreviated forms of the NRS name need
  490.     to be included here.
  491.  
  492. 2.  An academic site only on UUCP.
  493.     In this case you will need to specify a route to your Janet relay
  494.     site in your uucp.chn together with routes for all uucp sites which
  495.     do not go to the janet relay.  The entries for these will be similar
  496.     to those above.
  497.  
  498.     All other uk mail can be forwarded to the Janet relay in the top.chn,
  499.     e.g.
  500.         uk    cstvax.ed.ac.uk
  501.  
  502.     Alternatively, this can be specified in the uucp.chn as
  503.     e.g.
  504.         uk    pathto!cstvax!%s
  505.  
  506. 3.  A commercial site on PSS.
  507.     This is very similar to the first case.  Most routing will be
  508.     done by the x25 software: academic sites will probably be relayed
  509.     to a Janet gateway, PSS sites will have direct connections and
  510.     the remaining UUCP sites will be forwarded to an appropriate
  511.     uucp relay on PSS (e.g. ukc.ac.uk).
  512.  
  513. 4.  A Commercial site only on UUCP.
  514.     Because commercial sites can only use Janet to send to academic
  515.     sites, you need to be two relays: your Janet relay for academic
  516.     sites and your UUCP relay for commercial sites.
  517.  
  518.     These relays can be specified in the uucp.chn file in the following
  519.     way:
  520.         ac.uk    path_to_my_janet_relay!%s
  521.         co.uk    path_to_my_uucp_relay!%s
  522.  
  523.     So, the uucp.chn contains routes for all sites not to be sent to
  524.     a relay, plus the two relay rules.
  525.  
  526.     As an example, the uucp.chn for spider.co.uk may look something
  527.     like:
  528.         cs.heriot-watt.ac.uk    hwcs!%s
  529.         cs.hw.ac.uk        hwcs!%s
  530.         dice.ferranti.co.uk    hwcs!dice!%s
  531.         dice.ferr.co.uk        hwcs!dice!%s
  532.         ac.uk            hwcs!cstvax!%s
  533.         co.uk            hwcs!stl!%s
  534.  
  535.  
  536. It is recommended that the old "site.uucp" domain names should also be
  537. included in the uucp channel tables for a transition period whilst
  538. people change over to the new naming scheme.
  539.  
  540.  
  541. Finally, in the local channel table you should have three names:
  542.  
  543.     a) your standard form name    (e.g. cs.heriot-watt.ac.uk)
  544.     b) your abbreviated form name    (e.g. cs.hw.ac.uk)
  545.     c) your old uucp name        (e.g. hwcs.uucp)
  546.  
  547. (plus host specific names if this is a multi-host site).
  548. SHAR_EOF
  549. if test 4566 -ne "`wc -c uknet.note`"
  550. then
  551. echo shar: error transmitting uknet.note '(should have been 4566 characters)'
  552. fi
  553. echo shar: extracting distribute.1 '(1611 characters)'
  554. cat << \SHAR_EOF > distribute.1
  555. .TH DISTRIBUTE 8 "UK-sendmail"
  556. .UC 4
  557. .SH NAME
  558. distribute - send mail to a distribution list
  559. .SH SYNOPSIS
  560. .B /usr/local/lib/distribute
  561. .B list-name
  562. .B addresses...
  563. .SH DESCRIPTION
  564. .I Distribute
  565. sends a mail message to users on a distribution list.
  566. It alters the message header received from a contributor
  567. mainly to arrange for any error messages to be
  568. returned to the list maintainer.
  569. .PP
  570. .I Distribute
  571. is normally invoked by sendmail from an alias entry in
  572. /usr/lib/aliases of the form:
  573. .PP
  574. .DT
  575. list-name: "|/usr/local/lib/distribute list-name users..."
  576. .PP
  577. With lists containing many names, which maybe subject to frequent
  578. alteration, it is best to store the usernames in a file and replace
  579. the list of users with an argument to read the file, i.e.
  580. .PP
  581. .nf
  582. list-name: "|/usr/local/lib/distribute list-name `cat\ filename`"
  583. .fi
  584. .PP
  585. (this tends to work better than using sendmail's :include: feature, which
  586. typically limits the length of the shell command line to 128 bytes).
  587. .PP
  588. There should be a second entry in /usr/lib/aliases for the list maintainer.
  589. This is the name of the list with "\-request" appended.  This should be
  590. aliased to the person who is responsible for maintaining the distribution
  591. list.
  592. e.g.
  593. .PP
  594. .DT
  595. list-name-request: postman-pat
  596. .PP
  597. .I Distribute
  598. should be setuid to one of sendmail's trusted users, so that
  599. it will set the sender address to that of the list maintainer.
  600. .SH FILES
  601. /usr/lib/aliases
  602. .SH "SEE ALSO"
  603. sendmail(8), aliases(5), newaliases(1)
  604. .br
  605. "Recommendations for implementors of the
  606. JNT Mail Protocol Specifications (MG.B)"
  607. by Steve Kille, April 1985
  608. .SH AUTHOR
  609. Jim Crammond
  610. SHAR_EOF
  611. if test 1611 -ne "`wc -c distribute.1`"
  612. then
  613. echo shar: error transmitting distribute.1 '(should have been 1611 characters)'
  614. fi
  615. echo shar: extracting README '(3084 characters)'
  616. cat << \SHAR_EOF > README
  617. This directory contains a couple of extra programs and documentation which
  618. are not part of the main configuration package, but which might be useful.
  619.  
  620. SysV.sh:    This script converts the BSD dependent code into
  621.         System V dependent code in the three MAKE files
  622.         (MAKE, dom/MAKE and chn/MAKE).  The main alterations
  623.         necessary are changing the format of the "echo" command
  624.         arguments, and replacing "cat -n" with "pr -n"  and
  625.         "fmt" with "nroff" (!).  Just run it in the top level
  626.         directory.
  627.  
  628. uumailclean, hhmailclean:
  629.         These are programs to clean up the mail queues for uucp and
  630.         hhcp.  These should be called from /usr/lib/crontab, say,
  631.         once a day.  Manual entry for both programs is supplied in
  632.         uumailclean.8c.  To make these programs:
  633.  
  634.             cc -O -c warn.c
  635.             cc -O -c -I$(UUCPFLAGS) uumailclean.c
  636.             cc -o uumailclean uumailclean.o warn.o -l$(UUCPLIB)/uulib.a
  637.             install -o uucp -g uucp -m 6110 uumailclean /usr/lib/uucp
  638.  
  639.             cc -O -c warn.c
  640.             cc -O -c -I$(X25FLAGS) hhmailclean.c
  641.             cc -o hhmailclean hhmailclean.o warn.o
  642.             install -m 755 hhmailclean /usr/lib/x25
  643.  
  644.         where UUCPFLAGS, UUCPLIB and X25FLAGS should be the same as
  645.         in Support/Makefile.
  646.  
  647.  
  648. checkaddr:    This is a shell script to verify a list of addresses.
  649.  
  650.         This should be installed in /usr/local/checkaddr.
  651.         Manual entry is supplied in checkaddr.1
  652.  
  653.         NOTE: This version will work for sendmail version 4.12
  654.         (i.e. the standard BSD4.2 version); to adapt it to work
  655.         version 4.40, run it through the following command:-
  656.         "sed s/12/40/ checkaddr | tr UVW VWX > /usr/local/checkaddr"
  657.  
  658.  
  659. distribute:    This is a shell script to mail a message on to a
  660.         distribution list, having altered some headers first.
  661.  
  662.         This should be installed in /usr/local/lib/distribute.
  663.         Manual entry is supplied in distribute.1
  664.  
  665.  
  666. sendproc.sh:    This is a shell script to generate two sendmail domain
  667.         tables from the NRS database file.  The first one is
  668.         the "uk.dom" file, which contains all the subdomains
  669.         of "ac.uk" and "co.uk".  It is recommended that you
  670.         do a `Namecheck' on the generated file, and remove
  671.         any name clashes. In particular, removing the entry
  672.         "co -> co.ac.uk" is probably essential.
  673.  
  674.         The second file generated is the "abbrev.dom" file which
  675.         maps abbreviated form to standard form names.  It trys
  676.         it optimise the table to reduce the number of sendmail
  677.         rules subsequently generated.  Note that inclusion of
  678.         this table will probably double the size of your
  679.         configuration file and hence double sendmail's startup
  680.         time.  It should only be used if the frozen configuration
  681.         facility works.  It should be possible to reverse this 
  682.         table to get sendmail to map standard form to abbreviated
  683.         form names.
  684.  
  685.  
  686. csnet.note:    This is a note giving some hints on how to use the
  687.         information service provided by sh.cs.net (csnet-sh.arpa)
  688.         to build domain and channel tables for csnet sites.
  689.  
  690.  
  691. uknet.note:    This is the note posted to uk.net last year on how to
  692.         configure sendmail to handle the new naming scheme which
  693.         is being adopted on UKnet. It may give a few useful hints.
  694. SHAR_EOF
  695. if test 3084 -ne "`wc -c README`"
  696. then
  697. echo shar: error transmitting README '(should have been 3084 characters)'
  698. fi
  699. echo shar: extracting uumailclean.c '(7456 characters)'
  700. cat << \SHAR_EOF > uumailclean.c
  701. #include "uucp.h"
  702. #include <sys/types.h>
  703. #include <sys/stat.h>
  704. #ifdef    BSD42
  705. #include <sys/dir.h>
  706. #endif    BSD42
  707. #ifdef    NDIR
  708. #include <ndir.h>
  709. #endif    NDIR
  710. #ifdef    LIBNDIR
  711. #include "LIBNDIR/ndir.h"
  712. #endif    LIBNDIR
  713.  
  714. /*
  715.  *  uumailclean  -  this program searches through the uucp spool directory
  716.  *    looking for mail files.  Files which have been around for longer
  717.  *    than "failtime" hours will be returned to the sender.  If a file
  718.  *    has been around longer than "warntime" hours, then a warning
  719.  *    message is sent (once) to the sender.
  720.  *
  721.  *    If you use L.dirs to specify subdirectories, then failtime and
  722.  *    warntime can be specified as 3rd and 4th arguments to the directory
  723.  *    entries respectively: e.g.   "C. 336 168 72"
  724.  *    By default, these times are 1 week and 3 days.
  725.  *
  726.  *    Written by Jim Crammond        <jim@cs.hw.ac.uk>    3/86
  727.  */
  728.  
  729. #define FAILTIME 168    /* default hours before returning the mail */
  730. #define WARNTIME 72    /* default hours before sending a warning */
  731.  
  732. #define WARNFILE UUCPDIR/uucp/warnlist.mail"
  733.  
  734. int    warntime, failtime;
  735.  
  736. main(argc, argv)
  737. char *argv[];
  738. {
  739. #ifdef    SUBCS
  740.     FILE *fdirs;
  741. #endif    SUBCS
  742.     char file[NAMESIZE];
  743.     char cdir[ MAXFULLNAME ];
  744.     char *flds[10];
  745.     int nflds, ret;
  746.     int orig_uid = getuid();
  747.  
  748.     strcpy(Progname, "uumailclean");
  749.     uucpname(Myname);
  750.     chkdebug(orig_uid);
  751.  
  752.     /* cd to spool */
  753.     ASSERT(subchdir(Spool) != -1, "cannot chdir to ", Spool, 0 );
  754.  
  755.     init_warnedlist(WARNFILE);
  756.  
  757. #ifdef SUBCS
  758.     fdirs=fopen(DIRFILE,"r");
  759.     ASSERT(fdirs != NULL, "uumailclean cannot open", DIRFILE, 0);
  760.  
  761.     while (cfgets(cdir, sizeof(cdir), fdirs) != NULL)
  762.     {    nflds = getargs( cdir, flds );
  763.         ASSERT(nflds >= 1, "BAD entry in", DIRFILE, 0);
  764.  
  765.         /* only interested in command files */
  766.         if (flds[0][0] != CMDPRE)
  767.             continue;
  768.  
  769.         failtime = (nflds > 2) ? atoi(flds[2]) : FAILTIME;
  770.         warntime = (nflds > 3) ? atoi(flds[3]) : WARNTIME;
  771.  
  772.         checkfiles(flds[0]);
  773.     }
  774. #else    SUBCS
  775.     failtime = FAILTIME;
  776.     warntime = WARNTIME;
  777.  
  778.     checkfiles(".");
  779. #endif    SUBCS
  780.  
  781.     exit(0);
  782. }
  783.  
  784.  
  785. /*
  786.  *  checkfiles  -  scan a directory looking for "old" control files.
  787.  *           For each one found, call fail or warn as appropriate.
  788.  */
  789. checkfiles(dir)
  790. char    *dir;
  791. {
  792.     DIR *dirp;
  793.     char    file[NAMESIZE];
  794.     struct    stat stbuf;
  795.     time_t    now;
  796.     int    hours;
  797.  
  798.     time(&now);
  799.  
  800.     DEBUG(5, "checkfiles(%s)\n", dir);
  801.     if ((dirp = opendir(dir)) == NULL)
  802.     {    printf("directory unreadable\n");
  803.         return;
  804.     }
  805.  
  806.     while (gnamef(dirp, file))
  807.     {    if (file[0] != CMDPRE)
  808.             continue;
  809.  
  810.         if (stat(subfile(file), &stbuf) == -1)
  811.         {    DEBUG(4, "stat on %s failed\n", file);
  812.             continue;
  813.         }
  814.  
  815.         if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
  816.             continue;
  817.  
  818.         hours = (int) (now - stbuf.st_mtime) / 3600;
  819.         if (hours >= failtime)
  820.             fail(file, hours);
  821.         else if (hours >= warntime)
  822.             warn(file, hours);
  823.     }
  824. }
  825.  
  826.  
  827. /*
  828.  *  fail  -  send a failure message to the sender and delete the mail.
  829.  */
  830. fail(cmdfile, hours)
  831. char    *cmdfile;
  832. int    hours;
  833. {
  834.     char    dfile[NAMESIZE], xfile[NAMESIZE];
  835.     char    host[NAMESIZE];
  836.     char    *from, **to;
  837.     char    *sender(), **recipients();
  838.  
  839.     DEBUG(4, "fail called on %s\n", cmdfile);
  840.     getfnames(cmdfile, dfile, xfile);
  841.  
  842.     if ((to = recipients(xfile)) == NULL)
  843.         return;
  844.     if ((from = sender(dfile)) == NULL)
  845.         return;
  846.     strcpy(host, &cmdfile[2]);
  847.     host[ strlen(cmdfile)-7 ] = '\0';
  848.  
  849.     sendfailure(from, to, host, hours, dfile);
  850.  
  851.     unlink(subfile(cmdfile));
  852.     unlink(subfile(dfile));
  853.     unlink(subfile(xfile));
  854.  
  855.     return;
  856. }
  857.  
  858.  
  859. /*
  860.  *  warn  -  send a warning message to the sender and add the control file
  861.  *         to the list of files for which warnings have been sent.
  862.  */
  863. warn(cmdfile, hours)
  864. char    *cmdfile;
  865. int    hours;
  866. {
  867.     char    dfile[NAMESIZE], xfile[NAMESIZE];
  868.     char    host[NAMESIZE];
  869.     char    *from, **to;
  870.     char    *sender(), **recipients();
  871.  
  872.     if (in_warnedlist(cmdfile))
  873.         return;
  874.  
  875.     DEBUG(4, "warn called on %s\n", cmdfile);
  876.     getfnames(cmdfile, dfile, xfile);
  877.  
  878.     if ((to = recipients(xfile)) == NULL)
  879.         return;
  880.     if ((from = sender(dfile)) == NULL)
  881.         return;
  882.     strcpy(host, &cmdfile[2]);
  883.     host[ strlen(cmdfile)-7 ] = '\0';
  884.  
  885.     sendwarning(from, to, host, hours, failtime, dfile);
  886.  
  887.     add_warnedlist(cmdfile);
  888.  
  889.     return;
  890. }
  891.  
  892. /*
  893.  *  getfnames  -  read the control file to find the data and execute files
  894.  *          which contain the message and list of recipients.
  895.  *          dfile is set to the datafile, xfile to the execute file.
  896.  */
  897. getfnames(cmdfile, dfile, xfile)
  898. char    *cmdfile;
  899. char    *dfile;
  900. char    *xfile;
  901. {
  902.     FILE    *fp;
  903.     char    dline[100], xline[100];
  904.     char    *wrkvec[10];
  905.  
  906.     if ((fp = fopen(subfile(cmdfile), "r")) == NULL)
  907.         return;
  908.  
  909.     if (fgets(dline, 100, fp) == NULL || fgets(xline, 100, fp) == NULL)
  910.     {    fclose(fp);
  911.         return;
  912.     }
  913.  
  914.     if (getargs(dline, wrkvec) <= QF_INDEX)
  915.     {    fclose(fp);
  916.         return;
  917.     }
  918.     strcpy(dfile, wrkvec[ QF_INDEX ]);
  919.  
  920.     if (getargs(xline, wrkvec) < QF_INDEX)
  921.     {    fclose(fp);
  922.         return;
  923.     }
  924.     strcpy(xfile, wrkvec[ QF_INDEX ]);
  925.  
  926.     fclose(fp);
  927. }
  928.  
  929. /*
  930.  *  recipients -  returns a list of recipients that the mail was intended
  931.  *          for, or NULL if the execute file is not a mail file.
  932.  */
  933. char    **
  934. recipients(xfile)
  935. char    *xfile;
  936. {
  937.     static    char rbuf[BUFSIZ];
  938.     static    char *tobuf[1000];    /* see uuxqt */
  939.     FILE    *fp;
  940.     char    *p, **t;
  941.  
  942.     if ((fp = fopen(subfile(xfile), "r")) == NULL)
  943.         return(NULL);
  944.  
  945.     while (fgets(rbuf, BUFSIZ, fp) != NULL)
  946.     {    if (rbuf[0] == X_CMD)
  947.         {    if (strncmp(rbuf, "C rmail ", 8) == SAME)
  948.             {    fclose(fp);
  949.  
  950.                 /* turn into an array of addresses */
  951.                 for (p = &rbuf[8], t=tobuf; *p;)
  952.                 {    while (*p == ' ' || *p == '\n')
  953.                         *p++ = '\0';
  954.                     *t = p;
  955.                     while (*p && *p != ' ' && *p != '\n')
  956.                         p++;
  957.                     if (*t != p)
  958.                         t++;
  959.                 }
  960.                 *t = NULL;
  961.                 return(tobuf);
  962.             }
  963.         }
  964.     }
  965.  
  966.     fclose(fp);
  967.     return(NULL);
  968. }
  969.  
  970. /*
  971.  *  sender  -  returns the sender address from the uucp from line,
  972.  *           or NULL if not found.
  973.  */
  974. char    *
  975. sender(dfile)
  976. char    *dfile;
  977. {
  978.     static    char sender[BUFSIZ];
  979.     char    buf[BUFSIZ];
  980.     FILE    *fp;
  981.  
  982.     if ((fp = fopen(subfile(dfile), "r")) == NULL)
  983.         return(NULL);
  984.  
  985.     if (fgets(buf, BUFSIZ, fp) == NULL)
  986.         return(NULL);
  987.  
  988.     if (sscanf(buf, "From %s", sender) == 1)
  989.     {    fclose(fp);
  990.         return(sender);
  991.     }
  992.  
  993.     fclose(fp);
  994.     return(NULL);
  995. }
  996.  
  997.  
  998. /*
  999.  *  exists  -  returns 1 if "file" exists, else 0.
  1000.  */
  1001. exists(file)
  1002. char    *file;
  1003. {
  1004.     return( access(subfile(file),0) == 0 );
  1005. }
  1006.  
  1007.  
  1008. /*
  1009.  *  print_message  -  print the message in "dfile" on the stream "outp".
  1010.  *              If the edited flag is set, then only print some
  1011.  *              interesting headers and the first few lines of the body.
  1012.  */
  1013. print_message(dfile, outp, edited)
  1014. char    *dfile;
  1015. FILE    *outp;
  1016. int    edited;
  1017. {
  1018.     FILE    *dfp;
  1019.     char    buf[BUFSIZ];
  1020.     int    iflg, linecount;
  1021.  
  1022.     if ((dfp = fopen(subfile(dfile), "r")) == NULL)
  1023.         return;
  1024.  
  1025.     /* skip unix from line */
  1026.     fgets(buf, BUFSIZ, dfp);
  1027.  
  1028.     /* print header */
  1029.     iflg = 0;
  1030.     while (fgets(buf, BUFSIZ, dfp) != NULL && buf[0] != '\n')
  1031.     {    if (edited)
  1032.         {    if (buf[0] == '\t' || buf[0] == ' ')
  1033.             {    if (iflg)
  1034.                     fputs(buf, outp);
  1035.                 continue;
  1036.             }
  1037.  
  1038.             if (!interested(buf))
  1039.             {    iflg = 0;
  1040.                 continue;
  1041.             }
  1042.             iflg = 1;
  1043.         }
  1044.         fputs(buf, outp);
  1045.     }
  1046.     putc('\n', outp);
  1047.  
  1048.     /* print body */
  1049.     linecount = 0;
  1050.     while (fgets(buf, BUFSIZ, dfp) != NULL)
  1051.     {    if (edited && ++linecount > 5)
  1052.         {    fprintf(outp, ".....\n");
  1053.             break;
  1054.         }
  1055.         fputs(buf, outp);
  1056.     }
  1057.     fclose(dfp);
  1058. }
  1059.  
  1060. static char    *headers[] = { "From:", "Date:", "To:", "Cc:", "Subject:", 0 };
  1061.  
  1062. /*
  1063.  *  interested  -  determine whether "hdr" is considered interesting
  1064.  *           and thus should be printed in edited mode.
  1065.  */
  1066. interested(hdr)
  1067. char    *hdr;
  1068. {
  1069.     char    **hp = headers;
  1070.  
  1071.     while (*hp)
  1072.     {    if (strncmp(hdr, *hp, strlen(*hp)) == SAME)
  1073.             return(1);
  1074.         hp++;
  1075.     }
  1076.     return(0);
  1077. }
  1078.  
  1079.  
  1080. cleanup(code)
  1081. int code;
  1082. {
  1083.     exit(code);
  1084. }
  1085. SHAR_EOF
  1086. if test 7456 -ne "`wc -c uumailclean.c`"
  1087. then
  1088. echo shar: error transmitting uumailclean.c '(should have been 7456 characters)'
  1089. fi
  1090. echo shar: extracting warn.c '(3988 characters)'
  1091. cat << \SHAR_EOF > warn.c
  1092. #include <stdio.h>
  1093.  
  1094. /*
  1095.  *  routines to maintain a list of mailfiles for which warning messages have
  1096.  *  been sent out, plus routines to send out warning and failure messages.
  1097.  *
  1098.  *  Written by Jim Crammond    <jim@cs.hw.ac.uk>    3/86
  1099.  */
  1100.  
  1101. #define SENDMAIL   "/usr/lib/sendmail"
  1102. #define NAMESIZE   15
  1103. #define BLKSIZE    ((BUFSIZ/NAMESIZE) - 1)
  1104.  
  1105. struct flist
  1106. {    char    fname[BLKSIZE][NAMESIZE];
  1107.     int    nused;
  1108.     struct    flist *next;
  1109. };
  1110.  
  1111.  
  1112. struct    flist    warnlist;
  1113. FILE    *warnfp;
  1114.  
  1115.  
  1116. /*
  1117.  *  Initialise list of files for which warning messages have already been sent.
  1118.  *  This involves reading the warnfile into a table, removing files which
  1119.  *  no longer exist (i.e. been sent or deleted), and writing this out again.
  1120.  */
  1121. init_warnedlist(warnfile)
  1122. char    *warnfile;
  1123. {
  1124.     struct    flist    *wp;
  1125.     char    warned[NAMESIZE], *p;
  1126.     int    i;
  1127.     char    *index();
  1128.  
  1129.     wp = &warnlist;
  1130.     wp->next = NULL;
  1131.     wp->nused = 0;
  1132.  
  1133.     if ((warnfp = fopen(warnfile, "r")) != NULL)
  1134.     {    while (fgets(warned, NAMESIZE, warnfp) != NULL)
  1135.         {    if ((p = index(warned, '\n')) != NULL)
  1136.                 *p = '\0';
  1137.  
  1138.             if (exists(warned))
  1139.             {    if (wp->nused >= BLKSIZE)
  1140.                 {    wp->next = (struct flist *) malloc(sizeof(warnlist));
  1141.                     wp = wp->next;
  1142.                     wp->next = (struct flist *) NULL;
  1143.                     wp->nused = 0;
  1144.                 }
  1145.                 strcpy(wp->fname[wp->nused], warned);
  1146.                 wp->nused++;
  1147.             }
  1148.         }
  1149.         fclose(warnfp);
  1150.     }
  1151.  
  1152.     /*
  1153.      *  Rewrite warnedlist removing files that no longer exist.
  1154.      *  Could be really paranoid here and create a temporary file
  1155.      *  first, rather than overwrite; in case of crashed
  1156.      */
  1157.     if ((warnfp = fopen(warnfile, "w")) != NULL)
  1158.     {    wp = &warnlist;
  1159.         while (wp)
  1160.         {    for (i=0; i < wp->nused; i++)
  1161.                 fprintf(warnfp, "%s\n", wp->fname[i]);
  1162.             wp = wp->next;
  1163.         }
  1164.         fflush(warnfp);
  1165.     }
  1166. }
  1167.  
  1168. /*
  1169.  *  Determine whether the given filename is in the warn list.
  1170.  *  Returns 1 if found, 0 otherwise.
  1171.  */
  1172. in_warnedlist(file)
  1173. char    *file;
  1174. {
  1175.     struct    flist    *wp = &warnlist;
  1176.     int    i;
  1177.  
  1178.     while (wp)
  1179.     {    for (i=0; i < wp->nused; i++)
  1180.         {    if (strcmp(file, wp->fname[i]) == 0)
  1181.                 return(1);
  1182.         }
  1183.         wp = wp->next;
  1184.     }
  1185.     return(0);
  1186. }
  1187.  
  1188. /*
  1189.  *  Add a filename to the warn list.
  1190.  */
  1191. add_warnedlist(file)
  1192. char    *file;
  1193. {
  1194.     fprintf(warnfp, "%s\n", file);
  1195. }
  1196.  
  1197.  
  1198. /*
  1199.  *  Send a Failed Mail message back to the sender, containing the whole
  1200.  *  of the failed message.
  1201.  */
  1202. sendfailure(sender, rcpts, host, hours, msgfile)
  1203. char    *sender;
  1204. char    **rcpts;
  1205. char    *host;
  1206. int    hours;
  1207. char    *msgfile;
  1208. {
  1209.     FILE    *out, *popen();
  1210.     char    cmd[50];
  1211.  
  1212.     sprintf(cmd, "%s -t", SENDMAIL);
  1213.     out = popen(cmd, "w");
  1214.     fprintf(out, "From: MAILER-DAEMON\nSubject:Failed Mail\nTo: %s\n\n", sender);
  1215.     fprintf(out, "After %d days (%d hours), your message to the following people:\n\n", hours/24, hours);
  1216.  
  1217.     /* put out recipents */
  1218.     while (*rcpts)
  1219.     {    fprintf(out, "\t%s  (host=%s)\n", *rcpts, host);
  1220.         rcpts++;
  1221.     }
  1222.  
  1223.     fprintf(out, "\ncould not be delivered.\n\n"); 
  1224.     fprintf(out, "   ----- Unsent message follows -----   \n");
  1225.  
  1226.     /*  print all of the message */
  1227.     print_message(msgfile, out, 0);
  1228.     pclose(out);
  1229.  
  1230.     return;
  1231. }
  1232.  
  1233.  
  1234. /*
  1235.  *  Send a Waiting Mail message back to the sender, containing a summary
  1236.  *  of the delayed message (to remind him/her what it was about!).
  1237.  */
  1238. sendwarning(sender, rcpts, host, hours, failtime, msgfile)
  1239. char    *sender;
  1240. char    **rcpts;
  1241. char    *host;
  1242. int    hours;
  1243. int    failtime;
  1244. char    *msgfile;
  1245. {
  1246.     FILE    *out, *popen();
  1247.     char    cmd[50];
  1248.  
  1249.     sprintf(cmd, "%s -t", SENDMAIL);
  1250.     out = popen(cmd, "w");
  1251.     fprintf(out, "From: MAILER-DAEMON\nSubject:Waiting Mail\nTo: %s\n\n",
  1252.              sender);
  1253.     fprintf(out, "After %d days (%d hours), your message to the following people:\n\n", hours/24, hours);
  1254.  
  1255.     /* put out recipents */
  1256.     while (*rcpts)
  1257.     {    fprintf(out, "\t%s  (host=%s)\n", *rcpts, host);
  1258.         rcpts++;
  1259.     }
  1260.  
  1261.     fprintf(out, "\nhas not yet been delivered. Attempts to deliver the message will\n");
  1262.     fprintf(out, "continue for %d more days. No further action is required by you.\n\n", (failtime-hours)/24);
  1263.     fprintf(out, "   ----- Queued message begins -----   \n");
  1264.  
  1265.     /*  print a summary of the message */
  1266.     print_message(msgfile, out, 1);
  1267.     pclose(out);
  1268.  
  1269.     return;
  1270. }
  1271. SHAR_EOF
  1272. if test 3988 -ne "`wc -c warn.c`"
  1273. then
  1274. echo shar: error transmitting warn.c '(should have been 3988 characters)'
  1275. fi
  1276. echo shar: extracting hhmailclean.c '(7113 characters)'
  1277. cat << \SHAR_EOF > hhmailclean.c
  1278. #include <stdio.h>
  1279. #include <sys/types.h>
  1280. #include <sys/stat.h>
  1281. #include "local.h"
  1282. #ifndef BSD4_2
  1283. #include "dir.h"
  1284. #else
  1285. #include <sys/dir.h>
  1286. #endif  BSD4_2
  1287. #include "hhcp.h"
  1288.  
  1289. /*
  1290.  *  hhmailclean  -  this program searches through the hhcp spool directory
  1291.  *    looking for mail files.  Files which have been around for longer
  1292.  *    than "failtime" hours will be returned to the sender.  If a file
  1293.  *    has been around longer than "warntime" hours, then a warning
  1294.  *    message is sent (once) to the sender.
  1295.  *
  1296.  *    These times can be specified using options -f and -w.
  1297.  *    By default, these times are 1 week and 3 days.
  1298.  *
  1299.  *    Written by Jim Crammond        <jim@cs.hw.ac.uk>    3/86
  1300.  */
  1301.  
  1302. #define FAILTIME 168    /* default hours before returning the mail */
  1303. #define WARNTIME 72    /* default hours before sending a warning */
  1304.  
  1305. #define WARNFILE "/usr/spool/hhcp/warnlist.mail"
  1306. #define MAILPRE     "/usr/spool/hhcp/M0"
  1307.  
  1308. int    warntime, failtime;
  1309. char    mfile[TEXTL];    /*  path of mailfile  */
  1310.  
  1311. main(argc, argv)
  1312. char *argv[];
  1313. {
  1314.     DIR *dirp;
  1315.     char    file[MAXNAMLEN];
  1316.     struct    direct    *dirent, *readdir();
  1317.     struct    stat stbuf;
  1318.     time_t    now;
  1319.     int    hours;
  1320.  
  1321.  
  1322.     /* cd to spool */
  1323.     chdir(SPOOLD);
  1324.  
  1325.     while (argc > 1 && argv[1][0] == '-')
  1326.     {    switch (argv[1][1])
  1327.         {    case 'f':
  1328.                 if (*&argv[1][2])
  1329.                     failtime = atoi(&argv[1][2]);
  1330.                 else
  1331.                 {    failtime = atoi(argv[2]);
  1332.                     argc--; argv++;
  1333.                 }
  1334.                 break;
  1335.             case 'w':
  1336.                 if (*&argv[1][2])
  1337.                     warntime = atoi(&argv[1][2]);
  1338.                 else
  1339.                 {    warntime = atoi(argv[2]);
  1340.                     argc--; argv++;
  1341.                 }
  1342.                 break;
  1343.             default:
  1344.                 fprintf(stderr, "unknown flag %s\n", argv[1]);
  1345.                 break;
  1346.         }
  1347.         argc--; argv++;
  1348.     }
  1349.  
  1350.     if (failtime == 0)
  1351.         failtime = FAILTIME;
  1352.     if (warntime == 0)
  1353.         warntime = WARNTIME;
  1354.  
  1355.     init_warnedlist(WARNFILE);
  1356.  
  1357.     time(&now);
  1358.  
  1359.     if ((dirp = opendir(".")) == NULL)
  1360.     {    printf("directory unreadable\n");
  1361.         exit(1);
  1362.     }
  1363.  
  1364.     while ((dirent = readdir(dirp)) != NULL)
  1365.     {    if (dirent->d_name[0] != 'P' || dirent->d_name[1] != 'B')
  1366.             continue;
  1367.  
  1368.         if (stat(dirent->d_name, &stbuf) == -1)
  1369.         {    printf("cannot stat %s\n", dirent->d_name);
  1370.             continue;
  1371.         }
  1372.  
  1373.         if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
  1374.             continue;
  1375.  
  1376.         hours = (int) (now - stbuf.st_mtime) / 3600;
  1377.         if (hours >= failtime)
  1378.             fail(dirent->d_name, hours);
  1379.         else if (hours >= warntime)
  1380.             warn(dirent->d_name, hours);
  1381.     }
  1382.     exit(0);
  1383. }
  1384.  
  1385.  
  1386. /*
  1387.  *  fail  -  send a failure message to the sender and delete the mail.
  1388.  */
  1389. fail(pbfile, hours)
  1390. char    *pbfile;
  1391. int    hours;
  1392. {
  1393.     FILE    *msgfp;
  1394.     char    pafile[MAXNAMLEN];
  1395.     char    *host, *from, **to;
  1396.     char    *gethost(), *sender(), **recipients();
  1397.  
  1398.     strcpy(pafile,pbfile);
  1399.     pafile[1] = 'A';
  1400.     host = gethost(pafile);
  1401.  
  1402.     if ((msgfp = fopen(pbfile, "r")) == NULL)
  1403.         return;
  1404.  
  1405.     if ((to = recipients(msgfp)) == NULL)
  1406.         return;
  1407.     if ((from = sender(msgfp)) == NULL)
  1408.         return;
  1409.  
  1410.     sendfailure(from, to, host, hours, pbfile);
  1411.  
  1412.     unlink(pafile);
  1413.     unlink(pbfile);
  1414.     unlink(mfile);
  1415.  
  1416.     return;
  1417. }
  1418.  
  1419.  
  1420. /*
  1421.  *  warn  -  send a warning message to the sender and add the control file
  1422.  *         to the list of files for which warnings have been sent.
  1423.  */
  1424. warn(pbfile, hours)
  1425. char    *pbfile;
  1426. int    hours;
  1427. {
  1428.     FILE    *msgfp;
  1429.     char    pafile[MAXNAMLEN];
  1430.     char    *host, *from, **to;
  1431.     char    *gethost(), *sender(), **recipients();
  1432.  
  1433.     if (in_warnedlist(pbfile))
  1434.         return;
  1435.  
  1436.     strcpy(pafile,pbfile);
  1437.     pafile[1] = 'A';
  1438.     host = gethost(pafile);
  1439.  
  1440.     if ((msgfp = fopen(pbfile, "r")) == NULL)
  1441.         return;
  1442.  
  1443.     if ((to = recipients(msgfp)) == NULL)
  1444.         return;
  1445.     if ((from = sender(msgfp)) == NULL)
  1446.         return;
  1447.  
  1448.     sendwarning(from, to, host, hours, failtime, pbfile);
  1449.  
  1450.     add_warnedlist(pbfile);
  1451.  
  1452.     return;
  1453. }
  1454.  
  1455. /*
  1456.  *  gethost  -  read the control file to determine if this is a mail file
  1457.  *        and to find the host it is queued for.
  1458.  */
  1459. char    *
  1460. gethost(pafile)
  1461. char    *pafile;
  1462. {
  1463.     FILE    *fp;
  1464.     static    TAB    table;
  1465.     char    *p;
  1466.     int    flds;
  1467.  
  1468.     if ((fp = fopen(pafile, "r")) == NULL)
  1469.         return(NULL);
  1470.  
  1471.     if (fread(&table, sizeof(table), 1, fp) != 1)
  1472.     {    fclose(fp);
  1473.         return;
  1474.     }
  1475.     fclose(fp);
  1476.  
  1477.     /* find 3rd string in text part and see if its a mailfile  */
  1478.     for (flds=0, p=table.text; flds < 2 && p < &table.text[TEXTL];)
  1479.         if (*p++ == '\0')
  1480.             flds++;
  1481.  
  1482.     if (strncmp(p, MAILPRE, strlen(MAILPRE)) != 0)
  1483.         return(NULL);
  1484.  
  1485.     strcpy(mfile, p);
  1486.  
  1487.     /*  1st string in text part is the hostname  */
  1488.     return(table.text);
  1489. }
  1490.  
  1491. /*
  1492.  *  recipients -  returns a list of recipients that the mail was intended
  1493.  *          for, or NULL if the execute file is not a mail file.
  1494.  */
  1495. char    **
  1496. recipients(msgfp)
  1497. FILE    *msgfp;
  1498. {
  1499.     static    char rbuf[BUFSIZ];
  1500.     static    char *tobuf[1000];
  1501.     char    buf[BUFSIZ];
  1502.     char    *c, *p, *rp, **t;
  1503.  
  1504.     rp = &rbuf[0];
  1505.     t = &tobuf[0];
  1506.     *t = rp;
  1507.     while (fgets(buf, BUFSIZ, msgfp) != NULL && buf[0] != '\n')
  1508.     {    c = buf;
  1509.         while (*c && *c != '\n')
  1510.         {    if (*c == ',')
  1511.             {    if (*t != rp)
  1512.                 {    *rp++ = '\0';
  1513.                     *++t = rp;
  1514.                 }
  1515.                 c++;
  1516.             }
  1517.             else
  1518.                 *rp++ = *c++;
  1519.         }
  1520.  
  1521.         if (*t != rp)
  1522.         {    *rp++ = '\0';
  1523.             *++t = rp;
  1524.         }
  1525.     }
  1526.     *t = NULL;
  1527.     return(tobuf);
  1528. }
  1529.  
  1530. /*
  1531.  *  sender  -  returns the sender address from the message header,
  1532.  *           or NULL if not found.
  1533.  */
  1534. char    *
  1535. sender(msgfp)
  1536. FILE    *msgfp;
  1537. {
  1538.     static    char sndbuf[BUFSIZ];
  1539.     char    buf[BUFSIZ];
  1540.     char    *p, *index();
  1541.     int    saved = 0;
  1542.  
  1543.     /*  msgfp already points to start of headers */
  1544.     while (fgets(buf, BUFSIZ, msgfp) != NULL && buf[0] != '\n')
  1545.     {    /*
  1546.          *  extract sender from one of the following headers,
  1547.          *  in order of preference: "Reply-To", "Sender", "From"
  1548.          */
  1549.         if (strncmp(buf, "Reply-To:", 9) == 0)
  1550.         {    strcpy(sndbuf, &buf[9]);
  1551.             saved = 2;
  1552.         }
  1553.         else if (saved < 2 && strncmp(buf, "Sender:", 7) == 0)
  1554.         {    strcpy(sndbuf, &buf[7]);
  1555.             saved = 1;
  1556.         }
  1557.         else if (saved < 1 && strncmp(buf, "From:", 5) == 0)
  1558.             strcpy(sndbuf, &buf[5]);
  1559.     }
  1560.  
  1561.     if ((p = index(sndbuf, '\n')) != NULL)
  1562.         *p = '\0';
  1563.  
  1564.     fclose(msgfp);
  1565.     return(sndbuf);
  1566. }
  1567.  
  1568.  
  1569. /*
  1570.  *  exists  -  returns 1 if "file" exists, else 0.
  1571.  */
  1572. exists(file)
  1573. char    *file;
  1574. {
  1575.     return( access(file,0) == 0 );
  1576. }
  1577.  
  1578.  
  1579. /*
  1580.  *  print_message  -  print the message in "dfile" on the stream "outp".
  1581.  *              If the edited flag is set, then only print some
  1582.  *              interesting headers and the first few lines of the body.
  1583.  */
  1584. print_message(pbfile, outp, edited)
  1585. char    *pbfile;
  1586. FILE    *outp;
  1587. int    edited;
  1588. {
  1589.     FILE    *pfp;
  1590.     char    buf[BUFSIZ];
  1591.     int    iflg, linecount;
  1592.  
  1593.     if ((pfp = fopen(pbfile, "r")) == NULL)
  1594.         return;
  1595.  
  1596.     /* skip JNT header */
  1597.     while (fgets(buf, BUFSIZ, pfp) != NULL && buf[0] != '\n')
  1598.         ;
  1599.  
  1600.     /* print header */
  1601.     iflg = 0;
  1602.     while (fgets(buf, BUFSIZ, pfp) != NULL && buf[0] != '\n')
  1603.     {    if (edited)
  1604.         {    if (buf[0] == '\t' || buf[0] == ' ')
  1605.             {    if (iflg)
  1606.                     fputs(buf, outp);
  1607.                 continue;
  1608.             }
  1609.  
  1610.             if (!interested(buf))
  1611.             {    iflg = 0;
  1612.                 continue;
  1613.             }
  1614.             iflg = 1;
  1615.         }
  1616.         fputs(buf, outp);
  1617.     }
  1618.     putc('\n', outp);
  1619.  
  1620.     /* print body */
  1621.     linecount = 0;
  1622.     while (fgets(buf, BUFSIZ, pfp) != NULL)
  1623.     {    if (edited && ++linecount > 5)
  1624.         {    fprintf(outp, ".....\n");
  1625.             break;
  1626.         }
  1627.         fputs(buf, outp);
  1628.     }
  1629.     fclose(pfp);
  1630. }
  1631.  
  1632. static char    *headers[] = { "From:", "Date:", "To:", "Cc:", "Subject:", 0 };
  1633.  
  1634. /*
  1635.  *  interested  -  determine whether "hdr" is considered interesting
  1636.  *           and thus should be printed in edited mode.
  1637.  */
  1638. interested(hdr)
  1639. char    *hdr;
  1640. {
  1641.     char    **hp = headers;
  1642.  
  1643.     while (*hp)
  1644.     {    if (strncmp(hdr, *hp, strlen(*hp)) == 0)
  1645.             return(1);
  1646.         hp++;
  1647.     }
  1648.     return(0);
  1649. }
  1650. SHAR_EOF
  1651. if test 7113 -ne "`wc -c hhmailclean.c`"
  1652. then
  1653. echo shar: error transmitting hhmailclean.c '(should have been 7113 characters)'
  1654. fi
  1655. echo shar: extracting uumailclean.8c '(1938 characters)'
  1656. cat << \SHAR_EOF > uumailclean.8c
  1657. .TH UUMAILCLEAN 8C "UK-Sendmail"
  1658. .UC 4
  1659. .SH NAME
  1660. uumailclean \- uucp spool directory mail clean-up
  1661. .br
  1662. hhmailclean \- hhcp spool directory mail clean-up
  1663. .SH SYNOPSIS
  1664. .B /usr/lib/uucp/uumailclean
  1665. .PP
  1666. .B /usr/lib/uucp/hhmailclean
  1667. [
  1668. .BI \-f failtime
  1669. ] [
  1670. .BI \-w warntime
  1671. ]
  1672. .SH DESCRIPTION
  1673. .I Uumailclean
  1674. scans the uucp spool directory for mail files and checks to see how long
  1675. they have been queued.
  1676. If a mail message is found to have been queued for longer than 
  1677. .I failtime
  1678. hours, then it is returned to the sender and deleted from the queue.
  1679. If a mail message is found to have been queued for longer than
  1680. .I warntime
  1681. hours (but less than failtime), then
  1682. a warning message is sent to the sender to inform them that the mail
  1683. has yet to be delivered.
  1684. .I Hhmailclean
  1685. performs the same function on the hhcp spool directory.
  1686. .PP
  1687. By default, failtime is set to 168 hours (1 week) and warntime to 72 hours
  1688. (3 days). With the subdirectories option of UKUUCP,
  1689. .I uumailclean
  1690. will override these defaults if times are specified in the
  1691. .I L.dirs
  1692. file as 3rd and 4th arguments to the subdirectory entries. For example,
  1693. .nf
  1694.         C.hwcs    336    96    48
  1695. .fi
  1696. specifies a failtime of 96 hours and a warntime of 48 hours.
  1697. .PP
  1698. The defaults can be overridden in
  1699. .I hhmailclean
  1700. with the options
  1701. .BI \-f failtime
  1702. and
  1703. .BI \-w warntime.
  1704. .PP
  1705. Both programs maintain a list of mail files for which warning messages
  1706. have already been sent out, so that the sender will only receive one
  1707. warning message.  This is normally the file
  1708. .I warnlist.mail
  1709. in the appropriate spool directory.
  1710. .PP
  1711. Both programs
  1712. will typically be started by
  1713. .IR cron (8).
  1714. .SH FILES
  1715. /usr/spool/uucp            uucp spool directory
  1716. .br
  1717. /usr/spool/uucp/warnlist.mail    list of warned mail files
  1718. .br
  1719. /usr/lib/uucp/L.dirs        list of subdirectories of spool
  1720. .br
  1721. /usr/spool/hhcp            hhcp spool directory
  1722. .br
  1723. /usr/spool/uucp/warnlist.mail    list of warned mail files
  1724. .SH "SEE ALSO"
  1725. sendmail(8), uuclean(8C)
  1726. .SH AUTHOR
  1727. Jim Crammond
  1728. SHAR_EOF
  1729. if test 1938 -ne "`wc -c uumailclean.8c`"
  1730. then
  1731. echo shar: error transmitting uumailclean.8c '(should have been 1938 characters)'
  1732. fi
  1733. echo shar: done with directory xtras
  1734. cd ..
  1735. #    End of shell archive
  1736. exit 0
  1737.  
  1738.